home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / SCSI Samples 1.0 / SCSI Inquiry Samples ƒ / SCSI Inquiry (Synch) 06⁄07 ƒ / Src / SCSIInquiry.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-16  |  6.8 KB  |  246 lines  |  [TEXT/KAHL]

  1. /*                                SCSIInquiry.c                            */
  2. /*
  3.  * SCSIInquiry.c
  4.  * Copyright © 1994 Apple Computer Inc. All rights reserved.
  5.  * This is a minimal sample to illustrate the Original SCSI Manager.
  6.  */
  7. #include "SCSIInquiry.h"
  8.  
  9. #ifndef THINK_C                /* MPW includes            */
  10. #include <Errors.h>
  11. #include <Script.h>
  12. #include <Types.h>
  13. #include <Files.h>
  14. #include <Resources.h>
  15. #include <QuickDraw.h>
  16. #include <Fonts.h>
  17. #include <Events.h>
  18. #include <Windows.h>
  19. #include <ToolUtils.h>
  20. #include <Memory.h>
  21. #include <Menus.h>
  22. #include <Lists.h>
  23. #include <Printing.h>
  24. #include <Dialogs.h>
  25. #include <StandardFile.h>
  26. #endif
  27.  
  28. #include <SCSI.h>
  29.  
  30. unsigned short            gTargetDevice = 0;    /* Using device at ID = 0    */
  31.  
  32. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  33.  * SCSI Definitions
  34.  */
  35. #define    kScsiStatusGood            0x00        /* Normal completion        */
  36. #define    kScsiCmdInquiry            0x12        /* Device inquiry command    */
  37.  
  38. struct SCSI_6_Byte_Command {                /* Six-byte command            */
  39.     unsigned char        opcode;                /*  0                        */
  40.     unsigned char        lbn3;                /*  1 lbn in low 5            */
  41.     unsigned char        lbn2;                /*  2                        */
  42.     unsigned char        lbn1;                /*  3                        */
  43.     unsigned char        len;                /*  4                        */
  44.     unsigned char        ctrl;                /*  5                        */
  45. };
  46. typedef struct SCSI_6_Byte_Command SCSI_6_Byte_Command;
  47.  
  48. struct SCSI_Inquiry_Data {                    /* Inquiry returns this        */
  49.     unsigned char        devType;            /*  0 Device type,            */
  50.     unsigned char        devTypeMod;            /*  1 Device type modifier    */
  51.     unsigned char        version;            /*  2 ISO/ECMA/ANSI version    */
  52.     unsigned char        format;                /*  3 Response data format    */
  53.     unsigned char        length;                /*  4 Additional Length        */
  54.     unsigned char        reserved5;            /*  5 Reserved                */
  55.     unsigned char        reserved6;            /*  6 Reserved                */
  56.     unsigned char        flags;                /*  7 Capability flags        */
  57.     unsigned char        vendor[8];            /*  8-15 Vendor-specific    */
  58.     unsigned char        product[16];        /* 16-31 Product id            */
  59.     unsigned char        revision[4];        /* 32-35 Product revision    */
  60.     unsigned char        vendorSpecific[20]; /* 36-55 Vendor stuff        */
  61.     unsigned char        moreReserved[40];    /* 56-95 Reserved            */
  62. };
  63. typedef struct SCSI_Inquiry_Data SCSI_Inquiry_Data;
  64.  
  65. SCSI_Inquiry_Data            gInquiryData;    /* Inquiry data goes here    */
  66. unsigned long                gInquirySize;    /* Number of bytes read        */
  67.  
  68. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  69.  * gSCSICommand is the command that we send to the device.
  70.  */
  71. SCSI_6_Byte_Command            gSCSICommand = {
  72.         kScsiCmdInquiry,                    /* Command                    */
  73.         0,                                    /* LBN 3 -- unused            */
  74.         0,                                    /* LBN 2 -- unused            */
  75.         0,                                    /* LBN 1 -- unused            */
  76.         sizeof (SCSI_Inquiry_Data),            /* Returned buffer length    */
  77.         0                                    /* Flags -- must be zero    */
  78.     };
  79.  
  80. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  81.  * gRequestTIB defines the buffer that SCSIRead reads into. Because
  82.  * the Inquiry command can return a variable-length record, we use a
  83.  * TIB with single-byte transfers and an internal counter so we can
  84.  * recover the actual transfer length. The four tib values are used
  85.  * as follows:
  86.  *        scInc...    Move one byte from the device to the buffer address
  87.  *                    and increment the buffer address pointer.
  88.  *        scAdd...    Add one to gInquirySize -- this gives the actual
  89.  *                    number of bytes transfered.
  90.  *        scLoop        Continue processing TIB instructions at the start
  91.  *                    until the maximum number of loops have been done.
  92.  *        scStop        End of the TIB.
  93.  * Note that this is an extremely inefficient TIB and should only be
  94.  * used for polled "administrative" requests that return a variable-
  95.  * length buffer.
  96.  */
  97. SCSIInstr                    gRequestTIB[] = {
  98.     { scInc,    0, 1 },
  99.     { scAdd,    0, 1 },
  100.     { scLoop,    (-2 * sizeof (SCSIInstr)),    sizeof (SCSI_Inquiry_Data)    },
  101.     { scStop,    0, 0 }
  102. };
  103.  
  104. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  105.  * Local functions and administrative variables.
  106.  */
  107. #ifndef FALSE
  108. #define FALSE            0
  109. #define TRUE            1
  110. #endif
  111.  
  112. #ifdef __powerc
  113. QDGlobals                qd;
  114. #endif
  115.  
  116. void                        DisplayError(
  117.         OSErr                    errorStatus
  118.     );
  119. OSErr                        DoSCSICommand(
  120.         unsigned short            targetID,
  121.         const Ptr                scsiCommand,
  122.         SCSIInstr                *requestTIB
  123.     );
  124. void                        DisplaySCSIInquiry(
  125.         long                    actualTransferCount
  126.     );
  127.  
  128. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  129.  * Local functions and administrative variables.
  130.  */
  131. void
  132. main(void)
  133. {
  134.         short                    i;
  135.         OSErr                    status;
  136.         EventRecord                eventRecord;
  137.         long                    actualTransferCount;
  138.             
  139.         MaxApplZone();        
  140.         InitGraf(&qd.thePort);
  141.         InitFonts();
  142.         InitWindows();
  143.         InitMenus();
  144.         TEInit();
  145.         InitDialogs(0);
  146.         for (i = 0; i < 3; i++)
  147.             EventAvail(everyEvent, &eventRecord);
  148.         gRequestTIB[0].scParam1 = (unsigned long) &gInquiryData;
  149.         gRequestTIB[1].scParam1 = (unsigned long) &gInquirySize;
  150.         status = DoSCSICommand(
  151.                     gTargetDevice,
  152.                     (const Ptr) &gSCSICommand,
  153.                     gRequestTIB
  154.                 );
  155.         /*
  156.          * Since the Device Inquiry command can return a variable-length
  157.          * record, we need to obtain the actual number of bytes that
  158.          * were read. There are two algorithms we can use here, that
  159.          * should result in the same data:
  160.          *    Since tib[0].scOpcode was scInc, tib[0].scParam1 will point to
  161.          *        the next byte to store. We can subtract the original buffer
  162.          *        pointer from that value to get the actual count.
  163.          *    Since tib[1].scOpcode was scAdd, gInquirySize will have the
  164.          *        actual count.
  165.          *    One or another of these two techniques can be used for this
  166.          *    type of data.
  167.          */
  168.         actualTransferCount =
  169.             gRequestTIB[0].scParam1 - (unsigned long) &gInquiryData;
  170.         if (actualTransferCount != gInquirySize)
  171.             DisplayError(paramErr);
  172.         if (status != noErr)
  173.             DisplayError(status);
  174.         DisplaySCSIInquiry(actualTransferCount);
  175.         ExitToShell();
  176. }
  177.  
  178.  
  179. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  180.  * Display the inquiry result.
  181.  */
  182. static void
  183. StoreString(
  184.         const unsigned char        *textPtr,
  185.         Size                    textLength,
  186.         StringPtr                result
  187.     )
  188. {
  189.         register short            i;
  190.         
  191.         for (i = textLength; i > 0; --i) {
  192.             if (textPtr[i - 1] != ' ' && textPtr[i - 1] != 0)
  193.                 break;
  194.         }
  195.         BlockMove(textPtr, &result[1], i);
  196.         result[0] = i;
  197. }
  198.  
  199. void
  200. DisplaySCSIInquiry(
  201.         long                    actualTransferCount
  202.     )
  203. {
  204.         Str255                    inquirySize;
  205.         Str255                    vendorName;
  206.         Str255                    productName;
  207.         Str255                    revisionLevel;
  208.         
  209.         NumToString(actualTransferCount, inquirySize);
  210.         StoreString(
  211.             gInquiryData.vendor,
  212.             sizeof gInquiryData.vendor,
  213.             vendorName
  214.         );
  215.         StoreString(
  216.             gInquiryData.product,
  217.             sizeof gInquiryData.product,
  218.             productName
  219.         );
  220.         StoreString(
  221.             gInquiryData.revision,
  222.             sizeof gInquiryData.revision,
  223.             revisionLevel
  224.         );
  225.         ParamText(inquirySize, vendorName, productName, revisionLevel);
  226.         NoteAlert(ALRT_Info, NULL);
  227. }
  228.  
  229.  
  230. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  231.  * Display an error alert.
  232.  */
  233. void
  234. DisplayError(
  235.         OSErr                    errorStatus
  236.     )
  237. {
  238.         Str255                    work;
  239.         
  240.         NumToString(errorStatus, work);
  241.         ParamText(work, "\p", "\p", "\p");
  242.         InitCursor();
  243.         StopAlert(ALRT_Error, NULL);
  244. }
  245.  
  246.